import type { ComponentType } from '../../../types/interfaces'
import type {
  ElementGroupType,
  IStyleGroup,
  selectedType,
  StyleComponentType,
  StyleProperty,
  StylePropertyItem,
} from '../interfaces'
import { UIComponent } from '../../../lib/abstract'
import { ToolKit } from '../../../lib/utils/toolkit'
import {
  CUSTOM_EVENTS,
  DEFAULT_STYLE_PROPERTIES_CONFIG,
  EDIT_TYPE_CONFIG,
  getElementProperties,
  getTitleThemeClassName,
  HOSTNAME,
  logger,
  PROCESS_PAGE_ELEMENTS,
  STYLE_PROPERTIES,
  STYLE_PROPERTY_GROUPS,
  valueFormatter,
} from '../../../types/constants'
import { SYMBOLS, ThemeType } from '../../../types/interfaces'
import { ColorPicker } from '../../color_picker'
import { RangeSlider } from '../../range_slider'
import { Select } from '../../select'
import { getStylePropertiesByGroup } from '../constants'
import { MyFavorites } from '../my_favorites'
import { styles } from './styles'

interface ElementStylePickerProps {
  id?: string
  onSelect: (element: selectedType, style: selectedType, value: string | undefined) => void
}

type OperateObjectType = 'element' | 'style'

export class ElementStylePicker extends UIComponent<ElementStylePickerProps> {
  id: string = 'element-style-picker'
  $element: JQuery<HTMLElement> | undefined = undefined
  // 基础数据
  private readonly elementsData = Object.values(PROCESS_PAGE_ELEMENTS[HOSTNAME] || {}).filter(item => item.edit !== false)
  private readonly stylesData = STYLE_PROPERTY_GROUPS
  // 组件默认文本
  private readonly searchToggleText = '启用样式名称搜索'
  private readonly elementPanelClassName = 'element-panel'
  private readonly elementPanelSelector: string = `.${this.elementPanelClassName}`
  private readonly stylePanelClassName = 'style-panel'
  private readonly stylePanelSelector = `.${this.stylePanelClassName}`
  private readonly stateClassName = 'selected'
  private readonly NoSelectElementText = `未选择『页面元素』`
  private readonly NoSelectStyleText = `未选择『元素样式』`
  // 组件默认选项类名
  // 选择的元素
  selectedElement: selectedType | null = null // 当前选中的元素选择器
  selectedStyle: selectedType | null = null
  // 搜索配置
  private isSearchElement: boolean = true
  private searchQuery: string = ''
  private lastSearchHadResults: boolean = true
  private lastEmptySearchQuery: string = ''

  // 调节组件实例
  controlInstances: {
    [property: string]: Array<ComponentType>
  } = {}

  forceRenderStyleControls: boolean = false

  readonly controlsContainerClassName = 'controls-container'
  readonly controlsClassName = 'controls-group'
  readonly controlsItemClassName = 'controls-item'
  readonly controlsSelector = '.style-editor .editor-content .edit-area'

  // 其他组件
  private favorites: MyFavorites

  get className(): string {
    return 'element-style-picker'
  }

  // 选择器配置
  ELEMENT_SELECTORS = {
    // 搜索相关
    searchInput: { selector: '.search-box input', dynamic: false },
    searchToggle: { selector: '.search-toggle input', dynamic: false },

    // 元素相关
    elementNoResultsAction: { selector: `${this.elementPanelSelector} .no-results-action`, dynamic: true },
    elementPanel: { selector: this.elementPanelSelector as string, dynamic: false },
    elementGroupHeaders: { selector: `${this.elementPanelSelector} .group-header`, dynamic: true },
    elementMenuGroups: { selector: `${this.elementPanelSelector} .menu-groups`, dynamic: true },
    elementMenuItems: { selector: `${this.elementPanelSelector} .menu-groups .group-items .menu-item`, dynamic: true },
    elementMenuItemsName: { selector: `${this.elementPanelSelector} .menu-groups .group-items .menu-item .item-name`, dynamic: true },
    elementStatusIcon: { selector: `${this.elementPanelSelector} .selection-status .status-icon`, dynamic: false },
    elementStatusText: { selector: `${this.elementPanelSelector} .selection-status .status-text`, dynamic: false },
    elementStatus: { selector: `${this.elementPanelSelector} .selection-status .status-item`, dynamic: false },

    // 样式相关
    styleNoResultsAction: { selector: `${this.stylePanelSelector} .no-results-action`, dynamic: true },
    stylePanel: { selector: this.stylePanelSelector as string, dynamic: false },
    styleGroupHeaders: { selector: `${this.stylePanelSelector} .group-header`, dynamic: true },
    styleMenuGroups: { selector: `${this.stylePanelSelector} .menu-groups`, dynamic: true },
    styleMenuItems: { selector: `${this.stylePanelSelector} .menu-groups .group-items .menu-item`, dynamic: true },
    styleMenuItemsName: { selector: `${this.stylePanelSelector} .menu-groups .group-items .menu-item .item-name`, dynamic: true },
    styleMenuItemsFavoriteIcon: { selector: `${this.stylePanelSelector} .menu-groups .group-items .menu-item .favorite-icon`, dynamic: true },
    styleStatusIcon: { selector: `${this.stylePanelSelector} .selection-status .status-icon`, dynamic: false },
    styleStatusText: { selector: `${this.stylePanelSelector} .selection-status .status-text`, dynamic: false },
    styleStatus: { selector: `${this.stylePanelSelector} .selection-status .status-item`, dynamic: false },
  }

  constructor(props: ElementStylePickerProps) {
    super(props)
    this.favorites = MyFavorites.getInstance({
      onSelect: (id: StyleProperty) => {
        this.handleFavoriteSelect(id)
      },
      onRemove: (id: StyleProperty) => {
        this.handleFavoriteRemove(id)
      },
    })
  }

  // =================================== 渲染 HTML ===================================
  render(): string {
    const searchPlaceholder = this.getPlaceholder()
    const searchToggleChecked = !this.isSearchElement ? 'checked' : ''

    return `
      <div class="${this.className}">
        <div class="editor-header ${getTitleThemeClassName('SECONDARY', ThemeType.LIGHT)}">
          <div class="header-icon">${SYMBOLS.UI.CURSOR}</div>
          <div class="header-title">选择项目</div>
        </div>
        <!-- 搜索栏 -->
        <div class="search-bar">
          <div class="search-box">
            <input type="text" 
              placeholder="${searchPlaceholder}" 
              value="${this.searchQuery}">
          </div>
          <div class="search-toggle-wrapper">
            <label class="search-toggle" for="search-target">
              <input id="search-target" type="checkbox" ${searchToggleChecked}>
              <span>${this.searchToggleText}</span>
            </label>
          </div>
        </div>

        <!-- 双面板布局 -->
        <div class="panels-wrapper">
          <!-- 左侧元素面板 -->
          <div class="panel ${this.elementPanelClassName}">
            <div class="selection-status">
                ${this.renderSelectionStatus('element', this.selectedElement, this.NoSelectElementText)}
            </div>
            <div class="menu-groups">
                ${this.renderElementPanel()}
            </div>
          </div>

          <!-- 分隔线 -->
          <div class="panel-divider"></div>

          <!-- 右侧样式面板 -->
          <div class="panel ${this.stylePanelClassName}">
            <div class="selection-status">
              ${this.renderSelectionStatus('element', this.selectedStyle, this.NoSelectStyleText)}
            </div>
            <div class="menu-groups">
                ${this.renderStylePanel()}
            </div>
          </div>
        </div>
      </div>
    `
  }

  /**
   * 渲染元素面板 HTML
   */
  private renderElementPanel(): string {
    const filteredElements = this.filterElements()
    return filteredElements && Object.keys(filteredElements).length > 0
      ? Object.entries(filteredElements).map(([category, group]) => {
          const attr = { icon: '🧩', label: group.name }
          return this.renderGroup('element', category, attr, group.items)
        }).join('')
      : this.renderEmptyState()
  }

  /**
   * 渲染样式面板 HTML
   */
  private renderStylePanel(): string {
    const groupsHtml = Object.entries(this.stylesData)
      .map(([group, attr]) => {
        const properties = this.filterStyles(group)
        if (properties.length === 0 && this.searchQuery)
          return '' // 搜索时没有匹配项则不显示分组

        return this.renderGroup('style', group, attr, properties)
      })
      .join('')

    // 处理空状态
    if (this.searchQuery && groupsHtml.trim() === '') {
    // 如果是连续空搜索且查询词未变化，则返回空字符串（不重新渲染）
      if (!this.lastSearchHadResults && this.lastEmptySearchQuery === this.searchQuery) {
        return ''
      }

      this.lastSearchHadResults = false
      this.lastEmptySearchQuery = this.searchQuery
      return this.renderEmptyState()
    }

    this.lastSearchHadResults = true
    return groupsHtml
  }

  /**
   * 渲染分组 HTML（支持元素/样式）
   */
  private renderGroup(type: OperateObjectType, group: string, attr: IStyleGroup, properties: StylePropertyItem[]): string {
    const shouldExpand = this.shouldExpandGroup(group)

    return `
      <div class="menu-group" data-group="${group}">
        <div class="group-header ${shouldExpand ? 'expanded' : ''}">
          <span class="group-icon">${attr.icon}</span>
          <span class="group-name">${attr.label}</span>
          <span class="group-cnt">(${properties.length})</span>
        </div>
        <div class="group-items ${shouldExpand ? 'expanded' : ''}">
          ${properties.map(prop => `
            <div class="menu-item" data-property="${prop.id}">
              <span class="item-name">${this.getPropertyName(prop.label)}</span>
              ${type === 'style'
                ? `<span class="favorite-icon" data-id="${prop.id}">${this.favorites.getFavoriteIcon(prop.id)}</span>`
                : ''}
            </div>
          `).join('')}
        </div>
      </div>
    `
  }

  /**
   * 渲染搜索空数据 HTML
   * @private
   */
  private renderEmptyState(): string {
    const content = this.isSearchElement
      ? '没有找到匹配的页面元素'
      : '没有找到匹配的样式属性'

    return `
    <div class="no-results">
      <div class="no-results-icon">🔍</div>
      <div class="no-results-text">${content}</div>
      <button class="no-results-action">清除搜索</button>
    </div>
  `
  }

  private renderStyleControls(property: StyleProperty): string {
    const config = STYLE_PROPERTIES[property]?.component
    if (!config)
      return ''

    const { count, layout, gap } = {
      ...DEFAULT_STYLE_PROPERTIES_CONFIG,
      ...config,
    }
    const layoutClass = `layout-${layout}`
    const style = `gap: ${gap}px; display: ${layout === 'horizontal' ? 'flex' : 'grid'};${config.extraStyles || ''}`

    return `
    <div class="${this.controlsClassName} ${layoutClass}" style="${style}">
      ${Array.from({ length: count }).map((_, i) => `
        <div class="${this.controlsItemClassName}" data-index="${i}"></div>
      `).join('')}
    </div>
  `
  }

  /**
   * 清理指定属性的组件实例
   */
  private clearControlInstances(property: string) {
    if (this.controlInstances[property]) {
      this.controlInstances[property].forEach((instance) => {
        instance.destroy() // 调用组件的销毁方法
      })
      delete this.controlInstances[property]
    }
  }

  /**
   * 渲染并挂载控制组件
   */
  private renderAndMountControls($editor: JQuery<HTMLElement>, property: StyleProperty) {
    if (!$editor || $editor.length === 0) {
      logger.warn(`[${this.name}] 未找到编辑器容器`)
      return
    }
    else if ($editor.length > 1) {
      logger.warn(`[${this.name}] 找到${$editor.length}个编辑器容器`)
      return
    }

    // 隐藏骨架屏
    $editor.find('.edit-skeleton').hide()

    // 创建控制面板容器
    const $controlsContainer = $editor?.find(`.${this.controlsContainerClassName}`)
    if (!$controlsContainer || $controlsContainer.length === 0) {
      $editor?.append(`<div class="${this.controlsContainerClassName}"></div>`)
    }

    // 获取最新容器
    const $container = $editor.find(`.${this.controlsContainerClassName}`)
    if ($container && $container.length) {
      // 渲染控制组件 HTML
      $container.html(this.renderStyleControls(property))
      // 挂载实际组件
      this.mountStyleControls(property, $container)
    }
  }

  /**
   * 挂载调节组件
   */
  private mountStyleControls(property: StyleProperty, $container: JQuery<HTMLElement>) {
    // 清理旧实例
    this.clearControlInstances(property)

    const config = STYLE_PROPERTIES[property]?.component
    if (!config)
      return

    const { type, count = 1, props = [] } = config

    // 初始化实例数组
    this.controlInstances[property] = []

    for (let i = 0; i < count; i++) {
      const componentProps = props[i] || {}

      // 创建组件实例
      const instance = this.createComponentInstance(type, {
        ...componentProps,
        id: `${this.controlsClassName}-${property}-${i}`,
        onChange: (value: any) => this.handleControlChange(property, i, value),
      })

      if (instance) {
        this.controlInstances[property].push(instance)

        // 渲染并挂载
        const $wrapper = $container.find(`.${this.controlsItemClassName}:nth-child(${i + 1})`)
        $wrapper.html(instance.render())
        instance.mount($wrapper)
      }
    }
  }

  /**
   * 卸载所有调节组件
   */
  unmountStyleControls(): void {
    Object.keys(this.controlInstances).forEach((property) => {
      this.clearControlInstances(property)
    })
    this.controlInstances = {}
  }

  /**
   * 渲染单个组件
   */
  private createComponentInstance(type: StyleComponentType, props: any): ComponentType | null {
    switch (type) {
      case 'RangeSlider':
        return new RangeSlider({
          id: props.id,
          label: String(props.label) || '大小',
          value: Number(props.value) || Number(props.min) || 0,
          min: props.min || 0,
          max: props.max || 100,
          step: props.step || 0.1,
          onChange: props.onChange || ((_value) => {}),
          showValue: props.showValue || true,
          valueFormatter: props.valueFormatter || valueFormatter,
          selectOptions: props.selectOptions,
        })

      case 'ColorPicker':
        return new ColorPicker({
          id: props.id,
          label: String(props.label) || '颜色',
          value: props.value || '#000000',
          text: props.value || '#000000',
          textPlaceholder: props.textPlaceholder || '输入颜色',
          onChange: props.onChange || ((_value) => {}),
          showPreview: props.showPreview || true,
        })

      case 'Select':
        return new Select({
          id: props.id,
          label: props.label,
          options: props.options || [],
          selectedValue: props.selectedValue,
          onChange: props.onChange,
        })

      default:
        return null
    }
  }

  /**
   * 处理控件值变化
   */
  private handleControlChange(property: string, _index: number, value: any) {
    // 根据属性类型处理值
    let finalValue = value

    if (property === 'padding' || property === 'margin') {
      // 对于复合属性，需要构建字符串如 "10px 20px 10px 20px"
      const values = this.controlInstances[property].map(i => i)
      finalValue = values.join(' ')
    }

    // 触发回调
    this.props.onSelect(
      this.selectedElement,
      this.selectedStyle,
      finalValue,
    )
  }

  /**
   * 组件样式
   */
  styles(): string {
    return styles(this.className, this.stateClassName)
  }

  /**
   * 判断是否应该展开分组
   * @param _group 分组名称
   * @returns 是否应该展开
   */
  private shouldExpandGroup(_group: string): boolean {
    return this.searchQuery.length > 0
  }

  /**
   * 获取分组名称
   * @param _group 分组名称
   * @param label 分组标签
   * @returns 格式化后的分组名称
   */
  private getGroupName(_group: string, label: string): string {
    return `${label}`.replace(/([A-Z])/g, '$1').trim()
  }

  /**
   * 获取属性名称
   * @param prop 属性名称
   * @returns 格式化后的属性名称
   */
  private getPropertyName(prop: string) {
    return prop.replace(/([A-Z])/g, ' $1').trim()
  }

  // =================================== 事件绑定 ===================================
  /**
   * 绑定所有事件
   */
  bindEvents(): void {
    this.bindBaseEvents()
    this.bindElementEvents()
    this.bindStyleEvents()
  }

  /**
   * 绑定基本事件
   */
  bindBaseEvents(): void {
    this.handleSearchEvent()
    this.handleSearchToggle()
  }

  /**
   * 绑定元素事件
   */
  bindElementEvents(): void {
    this.handleGroupHeadersEvent('element')
    this.handleMenuItemsEvent('element')
    this.handleNoResultsAction('element')
  }

  /**
   * 绑定样式事件
   */
  bindStyleEvents(): void {
    this.handleGroupHeadersEvent('style')
    this.handleMenuItemsEvent('style')
    this.handleNoResultsAction('style')
  }

  // =================================== 处理事件 ===================================
  /**
   * 处理搜索事件
   */
  handleSearchEvent(): void {
    // 样式属性搜索框事件（防抖处理）
    const $searchInput = this.getElement('searchInput')
    if ($searchInput) {
      const handleInput = (e: Event) => {
        const $el = $(e.currentTarget as HTMLInputElement)
        this.searchQuery = String($el.val()).trim().toLowerCase()
        this.updateGroups()
      }

      $searchInput.on('input', ToolKit.func.debounce(handleInput, 500))
    }
  }

  /**
   * 处理搜索目标切换事件
   */
  handleSearchToggle(): void {
    this.getElement('searchToggle')?.on('change', (e) => {
      this.isSearchElement = !$(e.currentTarget as HTMLInputElement).is(':checked')
      this.updateSearchPlaceholder()
      logger.info(`[${this.name}] 搜索目标已切换为: ${this.isSearchElement ? '元素' : '样式'}`)
    })
  }

  /**
   * 公共分组标题点击处理
   */
  private handleCommonHeaderClick($header: JQuery<HTMLElement>) {
    const $group = $header.closest('.menu-group')
    const $items = $group.find('.group-items')

    $items.toggleClass('expanded')
    $header.toggleClass('expanded')
  }

  /**
   * 处理分组标题点击事件（区分元素和样式）
   */
  handleGroupHeadersEvent(type: OperateObjectType): void {
    if (type === 'element') {
      // 元素分组标题
      this.getElement('elementGroupHeaders')?.on('click', (e) => {
        const $header = $(e.currentTarget)

        this.handleCommonHeaderClick($header)

        logger.info(`[${this.name}] 已处理元素分组标题点击`)
      })
      return
    }

    // 样式分组标题
    this.getElement('styleGroupHeaders')?.on('click', (e) => {
      const $header = $(e.currentTarget)

      this.handleCommonHeaderClick($header)

      logger.info(`[${this.name}] 已处理样式分组标题点击`)
    })
  }

  /**
   * 公共选项点击处理
   */
  private handleCommonItemClick(
    type: OperateObjectType,
    $item: JQuery<HTMLElement>,
  ) {
    const $menuItem = $item.closest('.menu-item')
    const $menuGroup = $item.closest('.menu-group')
    const $groupName = $menuGroup.find('.group-name')

    const id = $menuItem.data('property')
    const name = $item.text().trim()

    const group = $menuGroup.data('group')
    const groupName = $groupName.text().trim()

    if (!id || !group)
      return

    // 当前选择与上次不同时更新UI
    if ((type === 'element' && this.selectedElement?.id !== id) || (type === 'style' && this.selectedStyle?.id !== id)) {
      this.highlightSelectedItem(type, id)
      logger.info(`[${this.name}] 已处理${type === 'element' ? '元素' : '样式'}选项点击`)
    }

    // 更新选中状态
    if (type === 'element') {
      this.selectedElement = { group, groupName, id, name }
    }
    else {
      // 样式项未创建编辑组件或强制渲染时时才会执行，避免重复创建
      if (this.selectedStyle?.id !== id || this.forceRenderStyleControls) {
        this.forceRenderStyleControls = false
        // 清空历史组件
        this.unmountStyleControls()
        // 渲染并挂载控制组件
        this.renderAndMountControls($(this.controlsSelector), id as StyleProperty)
      }
      this.selectedStyle = { group, groupName, id, name }
    }

    this.eventEmitter.emit(CUSTOM_EVENTS.EDIT_STEP, type === 'element'
      ? EDIT_TYPE_CONFIG.SELECT_ELEMENT
      : EDIT_TYPE_CONFIG.SELECT_STYLE)

    this.updateStatusText()
    this.props.onSelect(this.selectedElement, this.selectedStyle, undefined)
  }

  /**
   * 处理选项点击事件（区分元素和样式）
   */
  handleMenuItemsEvent(type: OperateObjectType): void {
    if (type === 'element') {
      // 点击元素菜单项
      this.getElement('elementMenuItemsName')?.on('click', (e: any) => {
        const $item = $(e.currentTarget)
        this.handleCommonItemClick(type, $item)
      })
      return
    }

    // 点击样式菜单项
    this.getElement('styleMenuItemsName')?.on('click', (e: any) => {
      const $item = $(e.currentTarget)
      this.handleCommonItemClick(type, $item)
      this.handleClickFavoriteIcon(e)
    })

    // 点击样式菜单项收藏图标
    this.getElement('styleMenuItemsFavoriteIcon')?.on('click', (e: any) => {
      this.handleClickFavoriteIcon(e)
    })
  }

  /**
   * 处理收藏图标点击事件（只用于样式）
   */
  handleClickFavoriteIcon(event: any): void {
    const $item = $(event.currentTarget)
    event.stopPropagation()
    const id = $item.data('id')
    const foundProperty = this.getStylePropertyWithFavoriteID(id)

    if (foundProperty) {
      this.favorites.toggleFavorite(foundProperty)
      // 更新图标状态
      $item.html(this.favorites.getFavoriteIcon(id))
    }
  }

  /**
   * 处理没有搜索结果的情况
   */
  handleNoResultsAction(type: OperateObjectType): void {
    const handler = () => {
      const $searchInput = this.getElement('searchInput')
      if ($searchInput) {
        $searchInput.val('')
        this.searchQuery = ''
        this.updateGroups()
      }
    }

    if (type === 'element') {
      this.getElement('elementNoResultsAction')?.on('click', () => {
        handler()
      })
      return
    }
    this.getElement('styleNoResultsAction')?.on('click', () => {
      handler()
    })
  }

  // =================================== 过滤选择项 ===================================
  /**
   * 过滤元素
   */
  private filterElements(): ElementGroupType {
    const elements = getElementProperties(this.elementsData)

    // 如果没有搜索词，返回所有元素
    if (!this.searchQuery) {
      return elements
    }

    // 创建过滤后的结果对象
    const filtered: ElementGroupType = {}

    Object.entries(elements).forEach(([category, group]) => {
      // 检查分类名称是否匹配
      const categoryMatch = group.name.toLowerCase().includes(this.searchQuery)

      // 过滤 items 中匹配的元素
      const matchedItems = group.items.filter(item =>
        item.label.toLowerCase().trim().includes(this.searchQuery),
      )

      // 如果分类匹配或该分类下有匹配的 items，则保留该分类
      if (categoryMatch || matchedItems.length > 0) {
        filtered[category] = {
          ...group,
          items: categoryMatch ? group.items : matchedItems,
        }
      }
    })

    return filtered
  }

  /**
   * 过滤样式
   * @param group 分组名称
   * @returns 过滤后的样式列表
   */
  private filterStyles(group: string): StylePropertyItem[] {
    const properties = getStylePropertiesByGroup(group)

    // 如果没有搜索词，返回所有属性
    if (!this.searchQuery) {
      return properties
    }

    // 检查搜索词是否匹配分组名称
    const groupLabel = this.stylesData[group]?.label || ''
    const groupName = this.getGroupName(group, groupLabel).toLowerCase()

    // 如果搜索词匹配分组名称，返回该分组所有属性
    if (groupName.includes(this.searchQuery)) {
      return properties
    }

    // 否则返回分组中匹配搜索词的属性
    return properties.filter((prop) => {
      const propName = this.getPropertyName(prop.label).toLowerCase()
      return propName.includes(this.searchQuery)
    })
  }

  // =================================== 处理选择 ===================================
  /**
   * 获取元素选择器
   */
  getElementSelector(): string {
    return this.elementsData.filter(item => item.id === this.selectedElement?.id || '')[0]?.selector || ''
  }

  /**
   * 高亮选中的项目（元素/样式）
   * @param type 操作类型
   * @param property 属性标识
   */
  private highlightSelectedItem(type: OperateObjectType, property: string): void {
    if (!this.isMainElementValid())
      return

    // 移除之前的高亮
    this.resetHighlightState(type)

    // 添加新高亮
    const $menuItem = this.$element?.find(
      `${this.ELEMENT_SELECTORS[`${type}MenuItems`].selector}[data-property="${property}"]`,
    )

    if ($menuItem?.length) {
      $menuItem.addClass(this.stateClassName)
      const $groupHeader = $menuItem.closest('.menu-group').find('.group-header')
      $groupHeader?.addClass(this.stateClassName)
    }

    logger.info(`[${this.name}] 当前${type === 'element' ? '元素' : '样式'}已高亮: ${property}`)
  }

  /**
   * 重置高亮状态
   * @param type 操作类型
   */
  private resetHighlightState(type: OperateObjectType): void {
    this.$element?.find(`${this.ELEMENT_SELECTORS[`${type}MenuItems`].selector}.${this.stateClassName}`)
      .removeClass(this.stateClassName)
    this.$element?.find(`${this.ELEMENT_SELECTORS[`${type}GroupHeaders`].selector}.${this.stateClassName}`)
      .removeClass(this.stateClassName)
  }

  /**
   * 渲染选择状态
   * @param type 类型
   * @param selectedItem 当前选中的项目
   * @param notSelectedText 未选中时的提示文本
   */
  private renderSelectionStatus(
    type: OperateObjectType,
    selectedItem: { group: string, id: string } | null,
    notSelectedText: string,
  ): string {
    // 未选中状态
    if (!selectedItem) {
      return `
      <div class="status-item not-selected">
        <span class="status-icon">${SYMBOLS.SHAPES.CIRCLE}</span>
        <span class="status-text">${notSelectedText}</span>
      </div>
    `
    }

    // 获取分组名称和项目名称
    const groupName = this.stylesData[selectedItem.group]?.label || selectedItem.group
    const itemName = type === 'element'
      ? this.getElementLabel(selectedItem.id)
      : this.getPropertyName(selectedItem.id)

    // 选中状态
    return `
      <div class="status-item selected">
        <span class="status-icon">${SYMBOLS.SHAPES.CIRCLE}</span>
        <span class="status-text">
          <span class="status-group">${groupName}</span>
          <span class="status-separator">-</span>
          <span class="status-item-name">${itemName}</span>
        </span>
      </div>
    `
  }

  /**
   * 获取元素显示名称
   */
  private getElementLabel(id: string): string {
    const element = this.elementsData.find(item => item.id === id)
    return element?.id || id
  }

  /**
   * 更新状态文本
   */
  updateStatusText(): void {
    // 统一处理状态更新
    const updateStatus = (
      type: OperateObjectType,
      selectedItem: { groupName: string, name: string } | null,
      notSelectedText: string,
    ) => {
      const selectorPrefix = `${type}Status`
      const text = selectedItem
        ? `已选择：${selectedItem.groupName}-${selectedItem.name}`
        : notSelectedText
      const className = selectedItem ? 'selected' : 'not-selected'

      this.getElement(`${selectorPrefix}Text`)?.text(text)
      this.getElement(selectorPrefix)
        ?.removeClass('selected not-selected')
        .addClass(className)
    }

    // 更新元素和样式状态
    updateStatus('element', this.selectedElement, this.NoSelectElementText)
    updateStatus('style', this.selectedStyle, this.NoSelectStyleText)
  }

  /**
   * 重置元素样式选择状态
   */
  resetStyleSelectStatus(): void {
    this.selectedStyle = null
    this.updateStatusText()
    this.resetHighlightState('style')
  }

  // =================================== 处理更新 ===================================
  /**
   * 获取搜索提示词
   */
  getPlaceholder(): string {
    return `${SYMBOLS.UI.SEARCH} ${this.isSearchElement ? '搜索待美化的『页面元素』...' : '搜索待调整的『元素样式』...'}`
  }

  /**
   * 更新搜索提示词
   * @private
   */
  private updateSearchPlaceholder(): void {
    if (!this.isMainElementValid())
      return

    const placeholder = this.getPlaceholder()

    this.getElement('searchInput')?.attr('placeholder', placeholder)
  }

  /**
   * 更新分组列表（区分元素和样式面板）
   */
  private updateGroups() {
    if (!this.isMainElementValid())
      return

    if (this.isSearchElement) {
    // 更新元素面板
      const $elementGroups = this.getElement('elementMenuGroups')
      if ($elementGroups) {
        $elementGroups.html(this.renderElementPanel())
        this.bindElementEvents()
        logger.info(`[${this.name}] 已更新元素面板`)
      }
    }
    else {
      // 更新样式面板
      const $styleGroups = this.getElement('styleMenuGroups')
      if ($styleGroups) {
        $styleGroups.html(this.renderStylePanel())
        this.bindStyleEvents()
        logger.info(`[${this.name}] 已更新样式面板`)
      }
    }
  }

  /**
   * 处理收藏项选择
   */
  private handleFavoriteSelect(id: StyleProperty) {
    const selector = `${this.ELEMENT_SELECTORS.styleMenuItems.selector}[data-property="${id}"] .item-name`
    const $item = this.$element?.find(selector)

    if (id && $item && $item.length > 0) {
      if ($item.length === 1) {
        this.handleCommonItemClick('style', $item)
      }
      else {
        logger.warn(`[${this.name}] 样式项 id 存在重复: ${id}，请检查样式配置`)
      }
    }
  }

  /**
   * 处理收藏项移除
   */
  private handleFavoriteRemove(id: StyleProperty) {
    const selector = `${this.ELEMENT_SELECTORS.styleMenuItems.selector}[data-property="${id}"] .favorite-icon`
    const $item = this.$element?.find(selector)
    if (id && $item && $item.length > 0) {
      $item.html(this.favorites.getFavoriteIcon(id))
    }
  }

  /**
   * 组件销毁时清理资源
   */
  destroy(): void {
    super.destroy()

    this.unmountStyleControls()
  }

  // =================================== 其他 ===================================
  /**
   * 通过收藏 ID 获取样式属性配置
   * @param id 收藏 ID
   */
  private getStylePropertyWithFavoriteID(id: string) {
    let foundProperty: StylePropertyItem | undefined

    Object.entries(this.stylesData).some(([group, _attr]) => {
      const properties = getStylePropertiesByGroup(group)
      const matchedProperty = properties.find(p => p.id === id)
      if (matchedProperty) {
        foundProperty = matchedProperty
        return true // 找到后终止循环
      }
      return false
    })

    return foundProperty
  }
}
